#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <functional>
#include "protocol.hpp"
#include<cassert>

// 我们要把tcp服务器设计为一个对象

// 默认端口
static const uint16_t default_port = 11111;
// 默认ip
static const std::string default_ip = "127.0.0.1";

namespace zxf
{
    class Tcp_client
    {
    public:
        Tcp_client(const std::string ip = default_ip, const int16_t port = default_port) // 构造函数
            : _ip(ip), _port(port), _listensock(-1)
        {
        }
        // 服务器初始化
        void initServer()
        {
            // std::cout<<"Tcp_server::initServer"<<std::endl;

            // 首先创建sock (socket)
            // 函数原型
            //        #include <sys/types.h>
            //        #include <sys/socket.h>
            //        int socket(int domain, int type, int protocol);
            // domain: 协议家族
            // type: 指定socket类型
            // protocol: 指定协议 ,为 0 会自动选择协议

            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock == -1)
            {
                std::cout << "socket error , exit" << std::endl;
                exit(1);
            }
            std::cout << "socket success!! " << std::endl;
        }

        // 开始运行服务器
        void start()
        {
            struct sockaddr_in net;
            socklen_t len = sizeof(net);
            bzero(&net, len);
            net.sin_family = AF_INET;
            net.sin_port = htons(_port);
            net.sin_addr.s_addr = inet_addr(_ip.c_str());
            // 发起链接
            //  #include <sys/types.h>
            //  #include <sys/socket.h>
            //  int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
            // 如果连接或绑定成功，则返回零。出现错误时，返回-1，并适当设置errno。
            int ret = connect(_listensock, (const sockaddr *)&net, len);
            if (ret < 0)
            {
                std::cout << "connect error , exit !! " << std::endl;
                exit(1);
            }
            std::cout << "connect success!! " << std::endl;

            for (;;)
            {
                // 处理信息
                std::string str;
                // istream& getline (istream& is, string& str);
                std::cout << "\n\n///format: \"10 + 10\""<<std::endl;
                std::cout << "Entry#";
                std::getline(std::cin, str);
                // 读取完成//字符处理
                int x = 10, y = 10;
                char op ='+';
                //10 + 10

                size_t pos1 = str.find(" ");
                size_t pos2 = str.rfind(" ");
                if(pos1 == std::string::npos && pos1 == std::string::npos)
                {
                    std::cout<<"输入格式不对"<<std::endl;
                    continue;
                }
                //10 + 10
                x = std::stoi(str.substr(0 , pos1));
                y = std::stoi(str.substr(pos2+1,std::string::npos));
                op = str[pos1+1];

                request_data req(x, y, op);
                //序列化
                std::string request_data_str = req.serialize();
                assert(!request_data_str.empty());

                std::cout << "request_data_str:"<<request_data_str<<std::endl;


                //添加报头
                std::string request_str = Headers(request_data_str);
                assert(!request_str.empty());
                

                //发送
                send(_listensock,request_str.c_str(),request_str.size(),0);//todo

                static std::string buf = ""; // 必须为静态
                std::string response_str = "";
                if (!complete_read(_listensock, response_str, buf))
                {
                    std::cout << "complete_read error , exit" << std::endl;
                    exit(1);
                }
                //数据读取完成

                
                //去掉报头
                std::string response_data_str = enHeaders(response_str);
                std::cout<<response_data_str<<std::endl;
                //反序列化
                response_data resp;
                resp.reserialize(response_data_str);
                
                std::cout<<"sss"<<std::endl;
                
                
                //客户端处理//此处可以独立出去hpp
                std::cout<<"errCode: "<<resp.get_errCode()<<std::endl;
                std::cout<<"result: "<<resp.get_result()<<std::endl;
            }
        }

    private:
        std::string _ip; // 远端服务器 IP
        int16_t _port;   // 远端服务器 port
        int _listensock;
    };

} // namespace zxf  end!!